package com.utils.jackson;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.TimeZone;

public class JSONUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger (JSONUtils.class);

    public static final ObjectMapper mapper = new ObjectMapper();
    // 日起格式化
    private static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";

    static {
        //对象的所有字段全部列入
        mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        //取消默认转换timestamps形式
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
        //忽略空Bean转json的错误
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS,false);
        //忽略 在json字符串中存在，但是在java对象中不存在对应属性的情况。防止错误
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
        mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT,true)
                .configure(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT,true);
        mapper.setTimeZone(TimeZone.getDefault());
        //所有的日期格式都统一为以下的样式，即yyyy-MM-dd HH:mm:ss
        mapper.setDateFormat(new SimpleDateFormat(STANDARD_FORMAT));
    }

    /**
     * 对象转字符串
     * @param object
     * @return
     */
    public static String toJSONString(Object object) {
        try {
            return mapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            LOGGER.error(">> parseObject failed ",e.getCause());
        }
        return null;
    }

    /**
     * 字符串转对象
     * @param json
     * @return
     */
    public static <T> T parseObject(String json, Class<T> clazz)  {
        try {
            if(StringUtils.isBlank(json)){
                return null;
            }
            json = removErrorString(json);
            return mapper.readValue(json, clazz);
        } catch (JsonMappingException e) {
            LOGGER.error(">> parseObject failed ",e.getCause());
        } catch (JsonProcessingException e) {
            LOGGER.error(">> parseObject failed ",e.getCause());
        }catch (Exception e) {
            LOGGER.error(">> parseObject failed ",e.getCause());
        }
        return null;
    }

    /**
     * 字符串转ObjectNode (ObjectNode类似 JSONObject)
     *
     * @param json
     * @return
     */
    public static JsonNode parseObject(String json)  {
        try {
            if(StringUtils.isBlank(json)){
                return null;
            }
            json = removErrorString(json);
            return mapper.readTree(json);
        } catch (JsonMappingException e) {
            LOGGER.error(">> parseObject to ObjectNode  failed ",e.getCause());
        } catch (JsonProcessingException e) {
            LOGGER.error(">> parseObject to ObjectNode  failed ",e.getCause());
        } catch (Exception e) {
            LOGGER.error(">> parseObject to ObjectNode  failed ",e.getCause());
        }
        return null;
    }
    public static ObjectNode createObjectNode()  {
        return mapper.createObjectNode();
    }
    /**
     * 字符串转对象列表
     * @param json
     * @param clazz
     * @param <T>
     * @return
     * @throws
     */
    public static <T> List<T> parseArray(String json, Class<T> clazz){
        try {
            if(StringUtils.isBlank(json)){
                return new ArrayList<>();
            }
            // 注意这里使用JavaType
            json = removErrorString(json);
            JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, clazz);
            return  mapper.readValue(json,javaType);
        } catch (JsonMappingException e) {
            LOGGER.error(">> parseArray failed ",e.getCause());
        } catch (JsonProcessingException e) {
            LOGGER.error(">> parseArray failed ",e.getCause());
        } catch (Exception e) {
            LOGGER.error(">> parseArray failed ",e.getCause());
        }
        return new ArrayList<>();
    }

    /**
     * 字符串转ArrayNode ,  (ArrayNode类似 JSONArray)
     * @param json
     * @return
     */
    public static ArrayNode parseArray(String json){
        try {
            json = removErrorString(json);
            JsonNode node = mapper.readTree(json);
            if(node.isArray()){
                return (ArrayNode)mapper.readTree(json);
            }
        } catch (JsonMappingException e) {
            LOGGER.error(">> parseArray to ArrayNode  failed ",e.getCause());
        } catch (JsonProcessingException e) {
            LOGGER.error(">> parseArray to ArrayNode  failed ",e.getCause());
        } catch (Exception e) {
            LOGGER.error(">> parseArray to ArrayNode  failed ",e.getCause());
        }
        return null;
    }

    public static String getString(JsonNode json, String fieldName)  {
        String result = "";
        if(json == null){
            return result;
        }
        try {
            JsonNode node = json.get(fieldName);
            if(node != null){
                result = node.asText();
            }
            return result;
        } catch (Exception e) {
            LOGGER.error(">> json is null ",e.getCause());
        }
        return result;
    }
    public static Integer getInt(JsonNode json, String fieldName)  {
        Integer result = null;
        if(json == null){
            return result;
        }
        try {
            JsonNode node = json.get(fieldName);
            if(node != null){
                result = node.asInt();
            }
            return result;
        } catch (Exception e) {
            LOGGER.error(">> json is null ",e.getCause());
        }
        return result;
    }
    public static Double getDouble(JsonNode json, String fieldName)  {
        Double result = null;
        if(json == null){
            return result;
        }
        try {
            JsonNode node = json.get(fieldName);
            if(node != null){
                result = node.asDouble();
            }
            return result;
        } catch (Exception e) {
            LOGGER.error(">> json is null ",e.getCause());
        }
        return result;
    }
    public static String getObj(JsonNode json, String fieldName)  {
        String result = "";
        if(json == null){
            return result;
        }
        try {
            JsonNode node = json.get(fieldName);
            if(node != null){
                result = node.toString();
            }
            return result;
        } catch (Exception e) {
            LOGGER.error(">> json is null ",e.getCause());
        }
        return result;
    }
    private static final  String ERROR_STRING = "Set[";
    private static final String ERROR_STRING_REG = "Set\\[";
    private static final String RIGHT_STRING = "[";
    /**
     *   为兼容老数据json 的序列化的废数据，需要将数据处理下
     * @param json
     * @return
     */
    public static String removErrorString(String json){
        if(json != null && json.contains(ERROR_STRING)){
            return json.replaceAll(ERROR_STRING_REG,RIGHT_STRING);
        }
        return json;
    }

}
